package com.bjc.test;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;

/**
 * @program: activiti_review
 * @description: 部署流程文件
 * @author: bjc
 * @create: 2021-11-15 21:40
 */
public class ActivitiDemo {

    /**
     * 测试流程部署
     */
    @Test
    public void testDeployment() {
        //1.创建processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3.使用service进行流程的部署，定义一个流程的名字，把bpmn和png部署到数据中
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn")
                .addClasspathResource("bpmn/evection.png")
                .deploy();
        //4.输出部署信息
        System.out.println("流程部署id = " + deploy.getId());
        System.out.println("流程部署名字 = " + deploy.getName());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void testStartProcess() {
        //1.创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //3.根据流程定义的id启动流程
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
        //4.输出内容
        System.out.println("流程定义id = " + instance.getProcessDefinitionId());
        System.out.println("流程实例id = " + instance.getId());
        System.out.println("当前活动的id = " + instance.getActivityId());
    }

    /**
     * 查询个人待执行的任务
     */
    @Test
    public void testFindPersonalTaskList() {
        //1.获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.获取taskService
        TaskService taskService = processEngine.getTaskService();
        //3.根据流程key和任务的负责人，查询任务
        List<Task> taskList = taskService.createTaskQuery()
                //流程key
                .processDefinitionKey("myEvection")
                //要查询的负责人
                .taskAssignee("zhangsan")
                .list();
        //4.输出
        for (Task task : taskList) {
            System.out.println("流程实例id=" + task.getProcessInstanceId());
            System.out.println("任务id=" + task.getId());
            System.out.println("任务负责人" + task.getAssignee());
            System.out.println("任务名称=" + task.getName());
        }
    }

    /**
     * 完成个人任务
     */
    @Test
    public void completeTask() {
        //获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //根据任务id完成任务   完成zhangsan的任务
//        taskService.complete("2505");
        //获取Jerry - myEvection对应的任务
//        Task task = taskService.createTaskQuery()
//                .processDefinitionKey("myEvection")
//                .taskAssignee("jerry")
//                .singleResult();
        //完成jack的任务
//        Task task = taskService.createTaskQuery()
//                .processDefinitionKey("myEvection")
//                .taskAssignee("jack")
//                .singleResult();
        //完成rose的任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("rose")
                .singleResult();
        System.out.println("流程实例id=" + task.getProcessInstanceId());
        System.out.println("任务id=" + task.getId());
        System.out.println("任务负责人" + task.getAssignee());
        System.out.println("任务名称=" + task.getName());
        //完成任务
        taskService.complete(task.getId());
    }

    /**
     * 使用zip包进行批量的部署
     */
    @Test
    public void deployProcessByZip() {
        //获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //流程部署
        //读取资源包文件，构成inputStream
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
        //用inputStream构造ZipInputStream
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        //使用压缩包的流进行流程的部署
        Deployment deploy = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
        System.out.println("流程部署的id=" + deploy.getId());
        System.out.println("流程部署的名称" + deploy.getName());
    }

    /**
     * 查询流程定义
     */
    @Test
    public void queryProcessDefinition() {
        //获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //获取ProcessDefinitionQuery对象
        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
        //查询当前所有的流程定义，返回流程定义信息的结合
        //processDefinitionKey(流程定义Key)
        //orderByProcessDefinitionVersion进行排序
        //desc倒叙
        //list查询所有的内容
        List<ProcessDefinition> definitionList = definitionQuery.processDefinitionKey("myEvection")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();
        //输出信息
        for (ProcessDefinition processDefinition : definitionList) {
            System.out.println("流程定义ID=" + processDefinition.getId());
            System.out.println("流程定义名称=" + processDefinition.getName());
            System.out.println("流程定义KEY=" + processDefinition.getKey());
            System.out.println("流程定义版本=" + processDefinition.getVersion());
            System.out.println("流程部署ID=" + processDefinition.getDeploymentId());
        }
    }

    /**
     * 删除流程部署信息
     * 当前的流程如果并没有完成，想要删除的画需要使用特殊方式，原理就是级联删除
     */@Test
    public void deleteDeployment() {
        //获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //通过引擎来获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //通过部署id来删除流程部署信息
        String deployment = "2501";
//        repositoryService.deleteDeployment(deployment);
        //第二个参数为true 表示级联删除
        repositoryService.deleteDeployment(deployment,true);
    }

    /**
     * 下载 资源文件
     * 方案一： 使用Activiti提供的API，来下载资源文件
     * 方案二： 自己写代码从数据库中下载文件，使用jdbc对blob类型，clob类型数据读取出来，保存到目录
     * 解决IO操作：commons-io.jar
     * 这里我们使用方案一：RepositoryService
     */
    @Test
    public void getDeployment() throws IOException {
        //1.得到引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.获取API，RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //获取查询对象ProcessDefinitionQuery:查询流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myEvection")
                .singleResult();
        //4.通过流程定义信息，获取部署ID
        String deploymentId = processDefinition.getDeploymentId();
        //5.通过RepositoryService，传递部署id参数，读取资源信息（png和bpmn）
        //  5.1获取png图片的流
        //从流程定义表中，获取png图片的目录和名字
        String pngName = processDefinition.getDiagramResourceName();
        //通过部署id和文件名字来获取图片的资源
        InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
        //  5.2获取bpmn的流
        String bpmnName = processDefinition.getResourceName();
        InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);
        //6.构造OutputStream流
        File pngFile = new File("E:\\evectionflow01.png");
        File bpmnFile = new File("E:\\evectionflow01.bpmn");
        FileOutputStream pngOutStream = new FileOutputStream(pngFile);
        FileOutputStream bpmnOutStream = new FileOutputStream(bpmnFile);
        //7.输入流，输出流的转换
        IOUtils.copy(pngInput,pngOutStream);
        IOUtils.copy(bpmnInput,bpmnOutStream);
        //8.关闭流
        pngOutStream.close();
        bpmnOutStream.close();
        pngInput.close();
        bpmnInput.close();
    }

    /**
     * 查看历史信息
     */
    @Test
    public void findHistoryInfo(){
//      获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
//        获取 actinst表的查询对象
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
//        查询 actinst表，条件：根据 InstanceId 查询
//        instanceQuery.processInstanceId("10001");
//        查询 actinst表，条件：根据 DefinitionId 查询
        instanceQuery.processDefinitionId("myEvection:1:7504");
//        增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//        查询所有内容
        List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
//        输出
        for (HistoricActivityInstance hi : activityInstanceList) {
            System.out.println(hi.getActivityId());
            System.out.println(hi.getActivityName());
            System.out.println(hi.getProcessDefinitionId());
            System.out.println(hi.getProcessInstanceId());
            System.out.println("<==========================>");
        }
    }
}
